package com.cryptape.cita_wallet.activity.bindwallet;

import android.content.Intent;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatEditText;
import android.text.InputType;
import android.text.TextUtils;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.blankj.utilcode.util.GsonUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.MapUtils;
import com.blankj.utilcode.util.ObjectUtils;
import com.blankj.utilcode.util.RegexUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.cryptape.cita.protocol.core.methods.response.AppSendTransaction;
import com.cryptape.cita_wallet.CytonApplication;
import com.cryptape.cita_wallet.activity.AdvanceSetupActivity;
import com.cryptape.cita_wallet.activity.NBaseActivity;
import com.cryptape.cita_wallet.activity.transfer.TransferPresenter;
import com.cryptape.cita_wallet.activity.transfer.TransferView;
import com.cryptape.cita_wallet.constant.ConstantUtil;
import com.cryptape.cita_wallet.event.TransferPushEvent;
import com.cryptape.cita_wallet.item.Wallet;
import com.cryptape.cita_wallet.item.transaction.AppTransaction;
import com.cryptape.cita_wallet.net.callback.CommonCallback;
import com.cryptape.cita_wallet.net.request.HttpRequestMode;
import com.cryptape.cita_wallet.net.response.BaseResponse;
import com.cryptape.cita_wallet.service.http.WalletService;
import com.cryptape.cita_wallet.util.AppUtils;
import com.cryptape.cita_wallet.util.Blockies;
import com.cryptape.cita_wallet.util.CurrencyUtil;
import com.cryptape.cita_wallet.util.NumberUtil;
import com.cryptape.cita_wallet.util.RSAUtils;
import com.cryptape.cita_wallet.util.db.DBWalletUtil;
import com.cryptape.cita_wallet.util.ether.EtherUtil;
import com.cryptape.cita_wallet.view.TitleBar;
import com.cryptape.cita_wallet.view.button.CommonButton;
import com.cryptape.cita_wallet.view.dialog.TransferDialog;
import com.mangoworld.android.R;

import org.greenrobot.eventbus.EventBus;
import org.web3j.protocol.core.methods.response.EthSendTransaction;

import java.math.BigInteger;
import java.util.Map;

import de.hdodenhof.circleimageview.CircleImageView;

public class BindMGPWalletActivity extends NBaseActivity implements TransferView {

    private TitleBar titleBar;
    private CircleImageView walletPhotoIv;
    private TextView walletNameTv;
    private TextView walletAddressTv;
    private TextView balanceTv;
    private TextView feeValueText, titleTv, addressTv;
    private AppCompatEditText bindAddressEt;
    private CommonButton nextStepBtn;
    private LinearLayout collectionAddressLayout;

    private static final int REQUEST_CODE_TRANSACTION = 0x02;
    public static final String EXTRA_TOKEN = "extra_token";
    public static final String EXTRA_ADDRESS = "extra_address";
    private static final String transferValue = "0.000001";
    private Wallet mWallet;
    private boolean isBalance = false;
    private TransferPresenter mPresenter;
    private double balance = 0;
    private TransferDialog transferDialog;
    private ProgressBar progressBar;
    private String address;
    private AppTransaction mAppTransaction = new AppTransaction();
    private boolean isToMgp = false;
    private double transferMgp = 0.000001;
    private String transferMgpStr = "";
    private int bindCode;
    private boolean isInitFee = false;

    @Override
    protected int getContentLayout() {
        return R.layout.activity_bind_mgp_wallet;
    }

    @Override
    protected void initView() {
        showProgressBar();
        titleBar = (TitleBar) findViewById(R.id.title);
        walletPhotoIv = (CircleImageView) findViewById(R.id.wallet_photo);
        walletNameTv = (TextView) findViewById(R.id.wallet_name);
        walletAddressTv = (TextView) findViewById(R.id.wallet_address);
        balanceTv = (TextView) findViewById(R.id.balanceTv);
        bindAddressEt = (AppCompatEditText) findViewById(R.id.bindAddressEt);
        nextStepBtn = (CommonButton) findViewById(R.id.next_action_button);
        feeValueText = (TextView) findViewById(R.id.fee_value_text);
        titleTv = (TextView) findViewById(R.id.titleTv);
        addressTv = (TextView) findViewById(R.id.addressTv);
        collectionAddressLayout = (LinearLayout) findViewById(R.id.collectionAddressLayout);
        addressTv.setText(ConstantUtil.getBindMgpChain());
        titleBar.setRightText(getString(R.string.str_record));
    }

    @Override
    protected void initData() {
        bindCode = getIntent().getIntExtra("bindCode", 0);
        mWallet = DBWalletUtil.getCurrentWallet(this);
        address = mWallet.address;
        walletAddressTv.setText(mWallet.address);
        walletNameTv.setText(mWallet.name);
        walletPhotoIv.setImageBitmap(Blockies.createIcon(mWallet.address));
        mPresenter = new TransferPresenter(mActivity, this);
        isToMgp = bindCode == 0;
        toMappingUI();
    }

    @Override
    protected void initAction() {
        titleBar.getDefaultRight().setOnClickListener(v -> {
            Intent intent = new Intent(BindMGPWalletActivity.this, BindHashRecordActivity.class);
            startActivity(intent);
        });
        nextStepBtn.setOnClickListener(v -> {
            if (isToMgp) {
                transferMgpStr = bindAddressEt.getText().toString().trim();
                try {
                    transferMgp = Double.parseDouble(transferMgpStr);
                } catch (Exception e) {
                    e.printStackTrace();
                    Toast.makeText(mActivity, R.string.input_correct_value_tip, Toast.LENGTH_SHORT).show();
                    return;
                }
                if (transferMgp <= 0) {
                    Toast.makeText(mActivity, R.string.transfer_amount_not_0, Toast.LENGTH_SHORT).show();
                    return;
                }
            }
            if (TextUtils.isEmpty(bindAddressEt.getText())) {
                Toast.makeText(mActivity, R.string.str_please_enter_eth_address, Toast.LENGTH_SHORT).show();
            } else if (isToMgp ? false : !RegexUtils.isMatch(ConstantUtil.REGEX_ACCOUNT_NAME, bindAddressEt.getText())) {
                Toast.makeText(mActivity, R.string.address_error, Toast.LENGTH_LONG).show();
            } else if (!mPresenter.isTransferFeeEnough()) {
                Toast.makeText(mActivity, String.format(getString(R.string.balance_not_enough_fee),
                        mPresenter.getFeeTokenUnit()), Toast.LENGTH_SHORT).show();
            } else if (mPresenter.checkTransferValueMoreBalance((isToMgp ? transferMgpStr : transferValue))) {
                ToastUtils.showLong(R.string.profile_hint_item300);
            } else {
                if (isToMgp) {
                    getConfirmTransferView();
                } else {
                    checkAddr();
                }
            }
        });
    }

    @Override
    public void updateAnyTokenBalance(Double balance) {
        isBalance = true;
        if (balance != null) {
            this.balance = balance;
            balanceTv.setText(String.format(getString(R.string.transfer_balance_place_holder),
                    CurrencyUtil.fmtMicrometer(NumberUtil.getDecimalValid_8(balance)) + " " + mPresenter.getTokenItem().getSymbol()));
        }
        if (isInitFee && isBalance) {
            dismissProgressBar();
        }
    }

    @Override
    public void updateNativeTokenBalance(Double balance) {

    }

    @Override
    public void updaterReceiveAddress(String address) {

    }

    @Override
    public void updateTitleData(String title) {

    }

    @Override
    public void updateWalletData(Wallet wallet) {

    }

    @Override
    public void startUpdateEthGasPrice() {

    }

    @Override
    public void updateEthGasPriceSuccess(BigInteger gasPrice) {

    }

    @Override
    public void updateEthGasPriceFail(Throwable throwable) {

    }

    @Override
    public void initTransferEditValue() {

    }

    boolean isTSS = true;

    @Override
    public void initTransferFeeView() {
//        mPresenter.updateGasPrice(new BigInteger("5"));
        feeValueText.setText(mPresenter.getTransferFee());
        initAdvancedSetup();
        if (isTSS) {
            isTSS = false;
            mPresenter.updateData("");
            mPresenter.updateGasLimit(new BigInteger("100000"));
            mPresenter.updateGasPrice(NumberUtil.getWeiFromGWeiForBigInt(Double.parseDouble("40")));
        }
        isInitFee = true;
        if (isInitFee && isBalance) {
            dismissProgressBar();
        }
    }

    @Override
    public void updateCITAQuota(String quotaFee) {
        isInitFee = true;
        feeValueText.setText(quotaFee);
        if (isInitFee && isBalance) {
            dismissProgressBar();
        }
    }

    @Override
    public void transferCITASuccess(AppSendTransaction appSendTransaction) {
        LogUtils.dTag("BindMGPWalletActivity==", "transferCITASuccess = ");
        progressBar.setVisibility(View.GONE);
        if (appSendTransaction == null) {
            Toast.makeText(mActivity, R.string.transfer_fail, Toast.LENGTH_SHORT).show();
        } else if (appSendTransaction.getError() != null
                && !TextUtils.isEmpty(appSendTransaction.getError().getMessage())) {
            Toast.makeText(mActivity, appSendTransaction.getError().getMessage(),
                    Toast.LENGTH_SHORT).show();
        } else if (!TextUtils.isEmpty(appSendTransaction.getSendTransactionResult().getHash())) {
            transferDialog.dismiss();
            EventBus.getDefault().post(new TransferPushEvent());
            finish();
        } else {
            Toast.makeText(mActivity, R.string.transfer_fail, Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void transferCITAFail(Throwable e) {
        LogUtils.dTag("BindMGPWalletActivity==", "transferCITAFail = ");
        progressBar.setVisibility(View.GONE);
        Toast.makeText(BindMGPWalletActivity.this,
                e.getMessage(), Toast.LENGTH_SHORT).show();
        transferDialog.dismiss();
    }

    @Override
    public void transferEtherSuccess(EthSendTransaction ethSendTransaction) {
        LogUtils.dTag("BindMGPWalletActivity==", "transferEtherSuccess = ");
        progressBar.setVisibility(View.GONE);
        if (ethSendTransaction == null) {
            Toast.makeText(mActivity, R.string.transfer_fail, Toast.LENGTH_SHORT).show();
        } else if (ethSendTransaction.getError() != null
                && !TextUtils.isEmpty(ethSendTransaction.getError().getMessage())) {
            Toast.makeText(mActivity, ethSendTransaction.getError().getMessage(),
                    Toast.LENGTH_SHORT).show();
        } else if (!TextUtils.isEmpty(ethSendTransaction.getTransactionHash())) {
            Toast.makeText(mActivity, R.string.transfer_success, Toast.LENGTH_SHORT).show();
            transferDialog.dismiss();
            EventBus.getDefault().post(new TransferPushEvent());
            if (isToMgp) {
                LogUtils.dTag("NumberUtil==2", "transferValue = " + NumberUtil.getDecimalValid_8((isToMgp ? transferMgp : Double.parseDouble(transferValue))) + " isToMgp = " + isToMgp);

                saveTransferHash(transferMgpStr, ethSendTransaction.getTransactionHash());
            } else {
                bindMgpChain(ethSendTransaction);
            }
        } else {
            Toast.makeText(mActivity, R.string.transfer_fail, Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void transferEtherFail(String message) {
        LogUtils.dTag("BindMGPWalletActivity==", "transferEtherFail message = " + message);
        progressBar.setVisibility(View.GONE);
        Toast.makeText(mActivity, message, Toast.LENGTH_SHORT).show();
        transferDialog.dismiss();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (transferDialog != null) {
            transferDialog.dismiss();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case REQUEST_CODE_TRANSACTION:
                switch (resultCode) {
                    case AdvanceSetupActivity.RESULT_TRANSACTION:
                        mAppTransaction = data.getParcelableExtra(AdvanceSetupActivity.EXTRA_TRANSACTION);
                        mPresenter.updateData(mAppTransaction.data);
                        if (mAppTransaction.isEthereum()) {
                            mPresenter.updateGasLimit(mAppTransaction.getGasLimit());
                            mPresenter.updateGasPrice(mAppTransaction.getGasPrice());
                        } else {
                            mPresenter.updateQuotaLimit(mAppTransaction.getQuota());
                        }
                        break;
                    default:
                        break;
                }
                break;
            default:
                break;
        }
    }

    private void initAdvancedSetup() {
        feeValueText.setTextColor(ContextCompat.getColor(mActivity, R.color.colorPrimary));
        feeValueText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(mActivity, AdvanceSetupActivity.class);
                intent.putExtra(AdvanceSetupActivity.EXTRA_TRANSFER, true);
                intent.putExtra(AdvanceSetupActivity.EXTRA_NATIVE_TOKEN, mPresenter.isNativeToken());
                mAppTransaction.chainType = mPresenter.isEther() ? ConstantUtil.TYPE_ETH : ConstantUtil.TYPE_CITA;
                mAppTransaction.data = mPresenter.getData();
                if (mPresenter.isEther()) {
                    mAppTransaction.setGasLimit(mPresenter.getGasLimit());
                    mAppTransaction.setGasPrice(mPresenter.getGasPrice());
                    mAppTransaction.chainId = EtherUtil.getEtherId();
                } else {
                    mAppTransaction.chainId = mPresenter.getTokenItem().getChainId();
                    mAppTransaction.setQuota(mPresenter.getQuotaLimit().toString());
                }
                intent.putExtra(AdvanceSetupActivity.EXTRA_ADVANCE_SETUP, mAppTransaction);
                startActivityForResult(intent, REQUEST_CODE_TRANSACTION);
            }
        });
    }


    private void toMappingUI() {

        if (isToMgp) {
            titleBar.showRight();
        } else {
            titleBar.hideRight();
        }
        nextStepBtn.button.setText(isToMgp ? R.string.str_immediately_mapping : R.string.next_action);
        collectionAddressLayout.setVisibility(isToMgp ? View.VISIBLE : View.GONE);
        titleTv.setText(isToMgp ? R.string.token_transfer_value : R.string.str_mgp_address);
        bindAddressEt.setHint(isToMgp ? R.string.token_transfer_value : R.string.str_please_enter_eth_address);
        bindAddressEt.setInputType(isToMgp ? InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL : InputType.TYPE_CLASS_TEXT);
    }

    public void setEditableEditText(AppCompatEditText editText, boolean isEnabled) {
        editText.setEnabled(isEnabled);//去掉点击时编辑框下面横线:
        editText.setFocusable(isEnabled);//不可编辑
        editText.setFocusableInTouchMode(isEnabled);//不可编辑
    }

    /**
     * show confirm transfer view
     */
    private void getConfirmTransferView() {
        if (isFastDoubleClick()) return;
        transferDialog = new TransferDialog(this, (password, progressBar) -> {
            this.progressBar = progressBar;
            transferDialog.setButtonClickAble(false);
            progressBar.setVisibility(View.VISIBLE);
            if (TextUtils.isEmpty(password)) {
                transferDialog.setButtonClickAble(true);
                progressBar.setVisibility(View.GONE);
                Toast.makeText(mActivity, R.string.password_not_null, Toast.LENGTH_SHORT).show();
            } else if (!WalletService.checkPassword(mActivity, password, mPresenter.getWalletItem())) {
                transferDialog.setButtonClickAble(true);
                progressBar.setVisibility(View.GONE);
                Toast.makeText(mActivity, R.string.password_fail, Toast.LENGTH_SHORT).show();
            } else {
                try {
                    if (!isToMgp) {
                        mPresenter.updateData(AppUtils.str2HexStr(bindAddressEt.getText().toString().trim()));
                    }
                    LogUtils.dTag("NumberUtil==", "transferValue = " + NumberUtil.getDecimalValid_8((isToMgp ? transferMgp : Double.parseDouble(transferValue))) + " isToMgp = " + isToMgp);
                    mPresenter.handleTransferAction(password, isToMgp ? transferMgpStr : transferValue, ConstantUtil.getBindMgpChain());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        transferDialog.setConfirmData(mPresenter.getWalletItem().address, ConstantUtil.getBindMgpChain(),
                NumberUtil.getDecimalValid_8((isToMgp ? transferMgp : Double.parseDouble(transferValue))) + mPresenter.getTokenItem().getSymbol(),
                ObjectUtils.isEmpty(mPresenter.getTransferFee()) ? "0" : mPresenter.getTransferFee());
    }

    public void checkAddr() {
        String bindAdress = bindAddressEt.getText().toString().trim();
        try {
            Map params = MapUtils.newHashMap();
            params.put("address", address);
            params.put("bindAdress", bindAdress);
            params.put("type", "1");
            String jsonData = GsonUtils.toJson(params);
            String content = RSAUtils.encrypt(jsonData);
            HttpRequestMode.checkAddr(BindMGPWalletActivity.this, content, true, new CommonCallback() {
                @Override
                public void onSuccess(Object data, String successMsg, int responseSuccessCode) {
                    if (data != null) {
                        //explain: 状态码说明: 0已绑定并且转了MGP, 1绑定中, 2需要绑定, 3系统错误判断, 4已绑定但未转MGP
                        LogUtils.dTag("BindMGPWalletActivity==", "checkAddr data = " + data.toString());
                        BaseResponse baseResponse = (BaseResponse) data;
                        switch (baseResponse.getResult()) {
                            case 0:
                            case 1:
                                ToastUtils.showLong(baseResponse.getMessage());
                                break;
                            case 2:
                                getConfirmTransferView();
                                break;
                            default:
                                break;
                        }
                    }
                }

                @Override
                public void onFailure(String msg, int responseFailCode) {
                    ToastUtils.showLong(msg);

                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void bindMgpChain(EthSendTransaction ethSendTransaction) {
        String bindAdress = bindAddressEt.getText().toString().trim();
        String hash = ethSendTransaction.getTransactionHash();
        String sender = DBWalletUtil.getCurrentWallet(CytonApplication.getInstance()).address;
        String moneyType = mPresenter.getTokenItem().getSymbol();
        try {
            Map params = MapUtils.newHashMap();
            params.put("currentAddr", sender);
            params.put("bindAddr", bindAdress);
            params.put("hash", hash);
            params.put("type", "1");
            params.put("money", "0.000001");
            String jsonData = GsonUtils.toJson(params);
            String content = RSAUtils.encrypt(jsonData);
            HttpRequestMode.bindMgpChain(BindMGPWalletActivity.this, content, true, new CommonCallback() {
                @Override
                public void onSuccess(Object data, String successMsg, int responseSuccessCode) {
                    if (data != null) {
                        //explain: 状态码说明: 0已绑定并且转了MGP, 1绑定中, 2需要绑定, 3系统错误判断, 4已绑定但未转MGP
                        LogUtils.dTag("BindMGPWalletActivity==", "bindMgpChain data = " + data.toString());
                        BaseResponse baseResponse = (BaseResponse) data;
                        switch (baseResponse.getResult()) {
                            case 0:
                                break;
                            default:
                                ToastUtils.showLong(baseResponse.getMessage());
                                break;
                        }
                    }
                    finish();
                }

                @Override
                public void onFailure(String msg, int responseFailCode) {
                    ToastUtils.showLong(msg);
                    finish();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void saveTransferHash(String num, String hash) {
        try {
            Map params = MapUtils.newHashMap();
            params.put("address", address);
            params.put("num", num);
            params.put("hash", hash);
            String jsonData = GsonUtils.toJson(params);
            String content = RSAUtils.encrypt(jsonData);
            HttpRequestMode.saveTransferHash(BindMGPWalletActivity.this, content, true, new CommonCallback() {
                @Override
                public void onSuccess(Object data, String successMsg, int responseSuccessCode) {
                    if (data != null) {
                        //explain: 状态码说明: 0已绑定并且转了MGP, 1绑定中, 2需要绑定, 3系统错误判断, 4已绑定但未转MGP
                        LogUtils.dTag("BindMGPWalletActivity==", "saveTransferHash data = " + data.toString());
                        BaseResponse baseResponse = (BaseResponse) data;
                        switch (baseResponse.getResult()) {
                            case 0:
                                break;
                            case 1:
                                break;
                            case 2:
                                break;
                            case 3:
                                break;
                            case 4:
                                break;
                        }
                    }
                    finish();
                }

                @Override
                public void onFailure(String msg, int responseFailCode) {
                    finish();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
